// 集成所有的模块
#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cassert>
#include <functional>
#include <unordered_map>
#include <mutex>
#include <thread>
#include <memory>
#include <any>
#include <condition_variable>
#include <fstream>
#include <regex>
#include <cstring>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <sys/eventfd.h>
#include <arpa/inet.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <fcntl.h>
#include <atomic>

#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL DBG

#define LOG(level, format, ...)                                                                                        \
    do                                                                                                                 \
    {                                                                                                                  \
        if (level < LOG_LEVEL)                                                                                         \
            break;                                                                                                     \
        time_t t = time(NULL);                                                                                         \
        struct tm *ltm = localtime(&t);                                                                                \
        char tmp[32] = {0};                                                                                            \
        strftime(tmp, 31, "%H:%M:%S", ltm);                                                                            \
        fprintf(stdout, "[%p %s %s:%d] " format "\n", (void *)pthread_self(), tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
    } while (0)

#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)

#define DEFAULT_BUFFER_SIZE 1024
// Buffer模块设计
class Buffer
{
public:
    Buffer()
        : _buffer(DEFAULT_BUFFER_SIZE), _write_idx(0), _read_idx(0)
    {
    }

    // 将Begin(), WriteAdde(), ReadAddr()的返回值设置为char*防止设置为void*而找不到字节长度的情况
    char *Begin()
    {
        // begin()返回的是迭代器，迭代器解引用可以访问迭代器对应管理的数据，再对这个数据取地址即可
        return (&*_buffer.begin());
    }

    // 获取写入位置地址
    char *WriteAddr()
    {
        return (Begin() + _write_idx);
    }

    // 获取读取位置地址
    char *ReadAddr()
    {
        return (Begin() + _read_idx);
    }

    // 获写入位置之后的缓冲区大小
    uint64_t TailIdleSpace()
    {
        return (_buffer.size() - _write_idx);
    }

    // 获读取位置之前的缓冲区大小
    uint64_t HeadIdleSpace()
    {
        return _read_idx;
    }

    // 获取可读数据的大小
    uint64_t ReadAbleSize()
    {
        return (_write_idx - _read_idx);
    }

    // 将读取位置向后移动指定长度
    void MoveReadPos(uint64_t len)
    {
        assert(len <= ReadAbleSize());

        _read_idx += len;
    }

    // 将写入位置向后移动指定长度
    // 这里是将写入位置进行后移，默认不考虑有一部分的空间在_read_idx的前面，直接当成_read_idx在0位置即可
    void MoveWritePos(uint64_t len)
    {
        assert(len <= TailIdleSpace());

        _write_idx += len;
    }

    // 确保写入空间足够(移动 / 扩容)
    void EnsureAbleSpace(uint64_t len)
    {
        // 写入位置后续的空间大于len直接放回
        if (len < TailIdleSpace())
        {
            return;
        }

        // 写入位置后续的空间大于len直接放回
        // 1.只需移动即可
        if (len < (TailIdleSpace() + HeadIdleSpace()))
        {
            uint64_t rsz = ReadAbleSize();
            // 参数1：起始位置，参数2：结束位置，参数三：拷贝到哪里
            std::copy(ReadAddr(), ReadAddr() + rsz, Begin());
            _read_idx = 0;
            _write_idx = rsz;
        }
        else
        {
            // 2.需要扩容
            // 这里的扩容直接将容器扩容到_write_idx后续要跟上的数据大小
            // 不考虑_read_idx前面还有空间的情况：因为考虑进这个问题就是说要先将数据拷贝到最开始的位置，
            // 但是vector扩容大多为异地扩容，两次拷贝性能消耗太大
            _buffer.resize(_write_idx + len);
        }
    }

    // 读数据(数据读取到哪里 + 读取指定长度的数据(类似系统调用read()))
    void Read(void *buffer, uint64_t len) // 不把读取数据之后直接移动取得位置放在Read()中是因为有可能用户想在同一位置读取多次
    {
        // 在Read之前要确保希望读取的数据长度小于等于可读数据长度
        assert(len <= ReadAbleSize());

        // 将数据拷贝到buffer中
        std::copy(ReadAddr(), ReadAddr() + len, (char *)buffer);
    }

    // 读取数据并且移动读取位置
    void ReadAndPop(void *buffer, uint64_t len)
    {
        Read(buffer, len);
        MoveReadPos(len);
    }

    // 以字符串的形式来读取数据
    std::string ReadAsString(uint64_t len)
    {
        // 在Read之前要确保希望读取的数据长度小于等于可读数据长度
        assert(len <= ReadAbleSize());

        std::string str;
        str.resize(len);

        // 走到这里就是要将数据读取到str中
        // 不使用str.c_str()是因为其返回值是一个const char*类型,
        // str[0]是第零个元素，对第零个元素取地址就是char*类型
        Read(&str[0], len);
        return str;
    }

    std::string ReadAsStringAndPop(uint64_t len)
    {
        // 在Read之前要确保希望读取的数据长度小于等于可读数据长度
        assert(len <= ReadAbleSize());
        std::string str = ReadAsString(len);

        MoveReadPos(len);

        return str;
    }

    // 写数据(写入的数据在哪里 + 写入数据长度)
    void Write(const void *data, uint64_t len)
    {
        EnsureAbleSpace(len);
        char *d = (char *)data;

        std::copy(d, d + len, WriteAddr());
    }

    void WriteAndPush(const void *data, uint64_t len)
    {
        Write(data, len);

        MoveWritePos(len);
    }

    // 写入String中的数据
    void WriteString(const std::string &data) // data有size()成员函数不需要再传入len参数
    {
        EnsureAbleSpace(data.size());

        Write(data.c_str(), data.size());
    }

    void WriteStringAndPush(const std::string &data)
    {
        WriteString(data);

        MoveWritePos(data.size());
    }

    void WriteBuffer(Buffer &data)
    {
        // 将data中的可读的数据写入到buffer中
        Write(data.ReadAddr(), data.ReadAbleSize());
    }

    void WriteBufferAndPush(Buffer &data)
    {
        WriteBuffer(data);

        MoveWritePos(data.ReadAbleSize());
    }

    // 提供的获取换行符的接口为后续的对协议的支持做准备
    char *FindCRLF()
    {
        void *ret = memchr(ReadAddr(), '\n', ReadAbleSize()); // 在一块内存空间中查找指定的字符

        return (char *)ret;
    }

    // 获取一行数据并且加上换行符
    std::string GetLine()
    {
        char *pos = FindCRLF();
        if (pos == nullptr)
        {
            return "";
        }

        return ReadAsString(pos - ReadAddr() + 1);
    }

    std::string GetLineAndPop()
    {
        std::string str = GetLine();
        MoveReadPos(str.size());

        return str;
    }

    // 清理缓冲区
    void Clear()
    {
        // 只要将读取位置和写入位置置为0即可，后续写入覆盖掉原始的数据
        _write_idx = 0;
        _read_idx = 0;
    }

private:
    std::vector<char> _buffer; // 用于存储数据(充当缓冲区)
    uint64_t _write_idx;       // 写入位置
    uint64_t _read_idx;        // 读取位置
};

// Socket模块
#define DEFAULT_BACKLOG 1024
class Socket
{
public:
    Socket()
        : _sockfd(-1)
    {
    }

    Socket(int fd)
        : _sockfd(fd)
    {
    }

    ~Socket()
    {
        Close();
    }

    int Getfd()
    {
        return _sockfd;
    }

    // 创建套接字
    bool Creat()
    {
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_sockfd < 0)
        {
            ERR_LOG("CREAT FAILED!");
            return false;
        }
        DBG_LOG("CREAT SUS!");
        return true;
    }

    // 绑定地址信息
    bool Bind(const std::string &ip, uint16_t port)
    {
        // int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip.c_str());

        socklen_t len = sizeof(addr);
        int ret = bind(_sockfd, (const struct sockaddr *)&addr, len);
        if (ret < 0)
        {
            ERR_LOG("BIND FAILED!");
            return false;
        }

        return true;
    }

    // 开始监听
    // backlog：同一时间链接最大并发数
    bool Listen(int backlog = DEFAULT_BACKLOG)
    {
        int ret = listen(_sockfd, backlog);

        if (ret < 0)
        {
            ERR_LOG("LISTEN FAILED!");
            return false;
        }

        return true;
    }

    // 客户端向服务器发起链接(三次握手)
    bool Connect(const std::string &ip, uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip.c_str());

        socklen_t len = sizeof(addr);
        int ret = connect(_sockfd, (const struct sockaddr *)&addr, len);
        if (ret < 0)
        {
            ERR_LOG("CONNECT FAILED!");
            return false;
        }

        return true;
    }

    // 服务器链接获取新连接
    // 返回文件描述符不返回Socket对象来增加可用性
    int Accept()
    {
        // 不获取客户端的相关信息
        int ret = accept(_sockfd, nullptr, nullptr);
        if (ret < 0)
        {
            ERR_LOG("ACCEPT FAILED!");
            return -1;
        }

        return ret;
    }

    // 关闭Socket
    void Close()
    {
        if (_sockfd < 0)
        {
            ERR_LOG("ILLEGALITY SOCKFD!");
            return;
        }

        close(_sockfd);
    }

    // 发送数据和接收数据中的flag均表示阻塞or非阻塞，默认为阻塞
    // 发送数据
    ssize_t Send(const void *data, int len, int flag = 0)
    {
        // ssize_t send(int sockfd, const void *buf, size_t len, int flags);
        ssize_t size = send(_sockfd, data, len, flag);

        if (size < 0)
        {
            ERR_LOG("SEND FAILED!");
            return -1;
        }

        DBG_LOG("SEND SUS!");
        return size;
    }

    // 设置socket非阻塞发送
    ssize_t NonBlockSend(const void *buf, size_t len)
    {
        return Send(buf, len, MSG_DONTWAIT);
    }

    // 接收数据
    ssize_t Recv(void *buffer, int len, int flag = 0)
    {
        // ssize_t recv(int sockfd, void *buf, size_t len, int flags);
        ssize_t size = recv(_sockfd, buffer, len - 1, flag);

        if (size <= 0)
        {
            // 有两种情况：1.真的出错了
            //            2.被信号中断 or 读取到0
            if (errno == EAGAIN || errno == EINTR)
            {
                return 0;
            }

            ERR_LOG("RECV FAILED!");
            return -1;
        }

        DBG_LOG("RECV SUS!");
        return size;
    }

    // 设置套接字阻塞属性-- 设置为非阻塞
    void NonBlock()
    {
        // int fcntl(int fd, int cmd, ... /* arg */ );
        int flag = fcntl(_sockfd, F_GETFL, 0);
        fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
    }

    // 设置socket非阻塞发送
    ssize_t NonBlockRecv(void *buf, size_t len)
    {
        return Recv(buf, len, MSG_DONTWAIT);
    }

    // 设置套接字选项 -- 设置为开启地址端口重用
    void ReaseAddress()
    {
        // int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
        // ip 和 port 都要被设置，故系统调用两次
        int val = 1;
        int ret = setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int));
        if (ret < 0)
        {
            ERR_LOG("SETSOCKOPT FAILED!");
        }

        val = 1;
        ret = setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void *)&val, sizeof(int));
        if (ret < 0)
        {
            ERR_LOG("SETSOCKOPT FAILED!");
        }
    }

    // 向服务器发起链接和向客户端发起链接本质是上面的小接口的集合，
    // 两者都是创建链接只是功能不同
    // 向服务器发起链接
    // ip默认设置为 0.0.0.0 表示可以通过服务器所有的网卡来创建服务器链接
    bool CreatServerLink(uint16_t port, const std::string &ip = "0.0.0.0", bool block_flag = false)
    {
        // 1. 创建套接字
        if (Creat() == false)
        {
            return false;
        }

        // 5.启动地址重用
        ReaseAddress();
        
        // 2.绑定地址
        if (Bind(ip, port) == false)
        {
            return false;
        }

        // 3.开始监听
        if (Listen() == false)
        {
            return false;
        }

        // 4.设置为非阻塞，根据block_flag来确定是否阻塞
        if (block_flag)
        {
            NonBlock();
        }

        

        return true;
    }

    // 向客户端发起链接
    bool CreatClientLink(uint16_t port, const std::string &ip)
    {
        // 1.创建sock
        if (Creat() == false)
        {
            return false;
        }

        // 2.链接服务器
        if (Connect(ip, port) == false)
        {
            return false;
        }

        return true;
    }

private:
    int _sockfd;
};

class Poller;
class EventLoop;
// Channel模块：对描述符监控事件的管理
using EventCallback = std::function<void()>;
class Channel
{
public:
    // 存疑：Poller不是会自己再构造函数中调用epoll_creat吗????
    Channel(int fd, EventLoop *eventloop) // eventloop自己会构造一个poller对象
        : _fd(fd), _eventloop(eventloop), _events(0), _revents(0)
    {
       // DBG_LOG("CREAT Channel SUS!");
    }

    int Getfd()
    {
        return _fd;
    }

    uint32_t GetEvents()
    {
        return _events;
    }

    void Update();
    void Remove();

    // 设置revents，给EventLoop模块使用
    void SetRevents(uint32_t events)
    {
        _revents = events;
    }

    // 设置可读事件函数回调
    void SetReadCallback(const EventCallback &cb)
    {
        _read_callback = cb;
    }

    // 设置可写事件函数回调
    void SetWriteCallback(const EventCallback &cb)
    {
        _write_callback = cb;
    }

    // 设置错误事件函数回调
    void SetErrorCallback(const EventCallback &cb)
    {
        _error_callback = cb;
    }

    // 设置链接断开事件函数回调
    void SetCloseCallback(const EventCallback &cb)
    {
        _close_callback = cb;
    }

    // 设置任意事件触发函数回调
    void SetEventsCallback(const EventCallback &cb)
    {
        _events_callback = cb;
    }

    // 是否监控了可读，不是是否有可读事件触发
    bool ReadAble()
    {
        if ((_events & EPOLLIN))
        {
            return true;
        }

        return false;
    }

    // 是否监控了可写，不是是否有可写事件触发
    bool WriteAble()
    {
        if ((_events & EPOLLOUT))
        {
            return true;
        }

        return false;
    }
    // 以下五个接口都是对Channel类中的成员变量进行设置，并没有色湖之进内核epoll红黑树中
    // 启动事件可读
    void EnableRead()
    {
       // DBG_LOG("=== Channel::EnableRead called, fd=%d, events before=%u ===", _fd, _events);
        // 添加到对象的成员属性中 + 添加到内核中
        _events |= EPOLLIN;
        //DBG_LOG("=== Channel::EnableRead, events after=%u, calling Update ===", _events);
        Update();
        //DBG_LOG("=== Channel::EnableRead completed ===");
        fflush(stdout);
    }

    // 启动事件可写
    void EnableWrite()
    {
        // 添加到对象的成员属性中 + 添加到内核中
        _events |= EPOLLOUT;
        Update();
    }

    // 解除事件可读监控
    void DisableRead()
    {
        _events &= ~EPOLLIN;
    }

    // 解除事件可写监控
    void DisableWrite()
    {
        _events &= ~EPOLLOUT;

        Remove();
    }

    // 解除所有事件监控
    void DisableAll()
    {
        _events = 0;

        Remove();
    }

    // 移除事件：上述的对事件的操作都是事件存在于epoll红黑树上
    //          该接口用于将事件从红黑树上移除，EventsLoop使用
    void RemoveEvent() {}

    // 任意一个事件触发了都调用HandlerEvent函数，
    // 具体说明事件触发以及触发后的调用都由HandlerEvent根据_revents来判断
    void HandlerEvent()
    {
        // std::cout << "HandlerEvent" << std::endl;
        // 在调用回调函数之前要判断回调函数是否存在
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            // 任意事件的回调要放在上面，因为读取出错会导致链接被释放。
            // 无论是什么事件触发都要调用任意事件的回调
            // if (_events_callback)
            // {
            //     _events_callback();
            // }

            if (_read_callback)
            {
                _read_callback();
            }
        }

        // 有可能会释放链接的操作一次只处理一个
        if (_revents & EPOLLOUT)
        {
            if (_write_callback)
            {
                _write_callback();
            }
        }
        // 一旦出错，释放链接没必要调用任意事件的触发，任意调用放在处理错误回调之前来调用
        else if (_revents & EPOLLERR)
        {
            if (_error_callback)
            {
                _error_callback();
            }
        }
        else if (_revents & EPOLLHUP)
        {
            if (_close_callback)
            {
                _close_callback();
            }
        }

        if(_events_callback)
        {
            _events_callback();
        }
    }

private:
    int _fd;
    uint32_t _events;  // 要关注的事件
    uint32_t _revents; // 具体哪个事件被触发

    EventLoop *_eventloop;

    EventCallback _read_callback;   // 可读事件的回调
    EventCallback _write_callback;  // 可写事件的回调
    EventCallback _error_callback;  // 错误事件的回调
    EventCallback _close_callback;  // 挂断事件的回调
    EventCallback _events_callback; // 任意事件的回调(刷新活跃度)
};

// Poller类的设计
#define MAX_EPOLLEVENT_SIZE 1024
class Poller
{
    // 因为Channel对象中包含了文件描述符和要监控的事件，
    // 所以我们只需要传入一个Channel对象给epoll我们就可以对epoll红黑树进行增删改
private:
    // 对epoll的系列系统调用封装
    void Updata(Channel *channel, int op)
    {
        // int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
        int fd = channel->Getfd();
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = channel->GetEvents();
        int ret = epoll_ctl(_epfd, op, fd, &ev);

        if (ret < 0)
        {
            ERR_LOG("EPOLL_CTL FAIL");
        }

        return;
    }

    // 判断一个Channel是否已经添加了事件监控
    bool HasChannel(Channel *channel)
    {
        // std::cout<<"---------------------"<<std::endl;
        auto it = _channels.find(channel->Getfd()); // 问题在这里！！！！！！！
        // std::cout<<"---------------------"<<std::endl;
        if (it == _channels.end())
        {
            return false;
        }

        return true;
    }

public:
    Poller()
    {
        _epfd = epoll_create(MAX_EPOLLEVENT_SIZE);
        if (_epfd < 0) 
        {
            ERR_LOG("EPOLL CREATE FAILED!!");
            abort();//退出程序
        }
    }

    // 对Updatae的封装
    void UpdateEvent(Channel *channel)
    {
       // DBG_LOG("=== Poller::UpdateEvent called, fd=%d ===", channel->Getfd());
        // 先判断是否存在
        // std::cout<<"---------------------"<<std::endl;
        bool ret = HasChannel(channel); // 这里有问题！！！！！！！！！！！！！

        // std::cout<<"---------------------"<<std::endl;
        if (ret == false)
        {
          //  DBG_LOG("%d=== Adding new channel to epoll, fd=%d === events:%d", _epfd, channel->Getfd(), channel->GetEvents());
            // 不存在则添加(添加到内核 + 哈希表)
            _channels.insert(std::make_pair(channel->Getfd(), channel));
            return Updata(channel, EPOLL_CTL_ADD);
        }

       // DBG_LOG("=== Modifying existing channel in epoll, fd=%d ===", channel->Getfd());
        // 存在就修改
        return Updata(channel, EPOLL_CTL_MOD);
    }

    // 对Updatae的封装
    void RemoveEvent(Channel *channel)
    {
        // 从内核中删除 + 从哈希表中删除
        Updata(channel, EPOLL_CTL_DEL);

        _channels.erase(channel->Getfd());
    }

    // 对文件描述符事件就绪的监控
    void Poll(std::vector<Channel *> *active)
    {
        // DBG_LOG("%d=== Polling, monitoring %lu channels ===", _epfd, _channels.size());
        // int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
        int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENT_SIZE, -1);

        // DBG_LOG("=== epoll_wait returned %d events ===", nfds);
        if (nfds < 0)
        {
            if (errno == EINTR)
            {
                DBG_LOG("=== Poll interrupted by signal ===");
                return;
            }

            ERR_LOG("POLL FAILED!");
        }

        for (int i = 0; i < nfds; i++)
        {
            // DBG_LOG("=== Event %d: fd=%d, events=%u ===", i, _evs[i].data.fd, _evs[i].events);
            // 先在管理模块查找活跃的Channel对象是否存在，存在再emplace_back到vector中
            auto it = _channels.find(_evs[i].data.fd);
            assert(it != _channels.end());

            it->second->SetRevents(_evs[i].events);
            active->emplace_back(it->second);
        }
    }

private:
    // epoll模型的操作句柄
    int _epfd;

    // 获取epoll红黑树中的活跃链接
    struct epoll_event _evs[MAX_EPOLLEVENT_SIZE];

    // 对文件描述符和对应的事件的映射
    std::unordered_map<int, Channel *> _channels;
};

using TaskFun = std::function<void()>;
using ReleaseFun = std::function<void()>;
class EventLoop;
// 设计的一个任务类，是任务轮要执行的任务
class Task
{
public:
    Task(uint64_t id, uint32_t timeout, TaskFun func)
        : _id(id), _timeout(timeout), _tfunc(func), _iscancel(false)
    {
    }

    void SetReleaseFun(ReleaseFun rfunc)
    {
        _rfunc = rfunc;
    }

    // 根据定时轮的实现逻辑可以知道任务的执行在对象析构时
    ~Task()
    {
        if (_iscancel == false)
        {
            _tfunc();
        }

        _rfunc();
    }

    uint32_t Gettimeout()
    {
        return _timeout;
    }

    void SetCancel()
    {
        _iscancel = true;
    }

private:
    // 唯一的一个用户编号，要在外部统一设置进来，不可由执行流设置
    uint64_t _id;
    uint32_t _timeout; // 任务的超时时间(也是刷新延迟时间)

    // 对象要执行的任务
    TaskFun _tfunc;
    ReleaseFun _rfunc;

    // 是否取消相关任务
    bool _iscancel;
};

class EventLoop;
class TimeWheel
{
private:
    void Remove(uint64_t id);

    static int CreateTimerfd();

    void ReadTimerfd();

    // 秒针每秒向后走一次
    void Run();

    void OnTime();

    // 向哈希表中增加一个新的weak_ptr对象 + 轮子里面增加shared_ptr管理的Task对象
    void AddTimerInLoop(uint64_t id, uint32_t delay, const TaskFun &cb);

    // 轮子里面增加shared_ptr管理的Task对象
    void RefreshTimerInLoop(uint64_t id);

    // 取消定时任务方法：不能直接在数组中释放掉管理的对象，这并不会取消而是提前执行
    void CancelTimerInLoop(uint64_t id);

    bool HasTimerInLoop(uint64_t id);

public:
    // 如果std::vector<std::vector<std::shared_ptr<Task>>>类型，但没有指定大小。
    // 当程序尝试访问_wheel的索引时（例如在AddTimer、RefreshTimer和Run方法中），
    // 如果索引超出当前向量大小，就会导致内存访问越界，从而引发段错误。
    TimeWheel(EventLoop *loop);

    // 对于定时任务的操作：有可能会出现线程安全问题，
    // 比如一个线程对_task中的一个元素在进行刷新，同一时刻另外一个线程对同一元素进行删除
    // 我们要确保刷新等操作都要在同一个线程中，压入Eventloop的任务池
    void AddTimer(uint64_t id, uint32_t delay, const TaskFun &cb);

    void RefreshTimer(uint64_t id);

    void CancelTimer(uint64_t id);

    bool HasTimer(uint64_t id);
private:
    // 执行部分-->里面放着的是被管理的Task对象
    std::vector<std::vector<std::shared_ptr<Task>>> _wheel;

    // 管理部分
    // 1.weak_ptr解决了shared_ptr不能减到0的问题
    // 2.new_qus：当weak_ptr指向的对象的引用计数为0之后要将改智能指针对象从_mmap中删除，防止资源泄露
    //   solution：因为是Task对象在析构时要删除，那么在Task类中增加一个回调函数在析构时从_mmap中删除
    std::unordered_map<uint64_t, std::weak_ptr<Task>> _mmap;

    // 指针的位置，指针在哪里，哪里的智能指针对象就要被释放，当引用计数为0的时候Task对象被析构执行任务
    int _tick;
    // 秒数(数组的大小 | _tick的最大移动范围)
    int _capactiy;

    // 用于使TimerWheel没秒执行一次任务
    int _timerfd;
    // 用于管理_timerfd的Channel
    std::unique_ptr<Channel> _timer_channel;
    // 依赖的EventLoop对象
    EventLoop *_loop;
};

using Functor = std::function<void()>;
class EventLoop{

public:
    static int Createventfd()
    {
        uint64_t val = 0;
        int evfd = eventfd(val, EFD_NONBLOCK | EFD_CLOEXEC);
        if (evfd < 0)
        {
            ERR_LOG("EVENTFD CREAT FAILED!");
            abort();
        }

        return evfd;
    }

    void ReadEventfd()
    {
        // 向eventfd中读取数据
        uint64_t val = 1;
        int ret = read(_eventfd, &val, sizeof(val));
        if (ret < 0)
        {
            if (errno == EAGAIN || errno == EINTR)
            {
                DBG_LOG("TRY READ AGAIN!");
                return;
            }

            ERR_LOG("READ FAILED!");
            abort();
        }

        return;
    }

    void WeakUpEventfd()
    {
        // 向eventfd中写入数据
        uint64_t val = 1;
        int ret = write(_eventfd, &val, sizeof(val));
        if (ret < 0)
        {
            if (errno == EAGAIN || errno == EINTR)
            {
                DBG_LOG("TRY WRITE AGAIN!");
                return;
            }

            ERR_LOG("WRITE FAILED!");
            abort();
        }

        return;
    }
    // 构造
    EventLoop()
        : _eventfd(Createventfd()),
          _eventfd_channel(new Channel(_eventfd, this)),
          _thread_id(std::this_thread::get_id()),
          _time_wheel(this)
    {
        DBG_LOG("构造EventLoop..............%p", this);
        // 因为我们在初始化列表根据_eventfd生成了一个管理_eventfd的Channel对象
        // 所以我们在构造函数中要设置事件通知文件描述符的读事件回调和启动该Channel对象可读
        _eventfd_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd, this));

        // 启动管理_eventfd的Channel对象为可读的
        _eventfd_channel->ReadAble();
    }

    // 判断当前的执行线程是否为调用IsInLoop()函数的EventLoop对象(当前程序的执行流可能没有该任务对应的线程)
    // 因为我们对一个文件描述符对应一个EventLoop对象，一个EventLoop对象对应一个执行线程
    // 线程负责这个fd的事件监控，事件处理(回调)，所用的_task也是每个文件描述符会有一个，不会存在线程安全问题.
    bool IsInLoop()
    {
        // 根据EventLoop对应的线程ID和当前程序正在执行的线程ID来判断
        return (_thread_id == std::this_thread::get_id());
    }

    void AssertInLoop()
    {
        assert(_thread_id == std::this_thread::get_id());
    }

    // 将任务插入到任务池中(注意线程安全问题)
    void QueueInLoop(const Functor &fun)
    {
        // 出作用域自动解锁
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.push_back(fun);
        }

        // 唤醒有可能因为事件就绪，而导致的epoll阻塞，其实解决方法就是给eventfd写一个数据，就可以触发eventfd的可读事件
        WeakUpEventfd();
    }

    // 判断要执行的任务是否在线程中，如果是就运行，不是就插入任务池
    void IsRunInLoop(const Functor &cb)
    {
        if (IsInLoop())
        {
            // 任务在线程中直接运行
            return cb();
        }

        // 任务不在线程中，插入任务池
        QueueInLoop(cb);
    }

    // 添加/修改调用该接口的对象锁对应的文件描述符要监控的事件
    void UpdateEvent(Channel *channel)
    {
        _poller.UpdateEvent(channel);
    }

    // 移除调用该接口的对象锁对应的文件描述符要监控的事件
    void RemoveEvent(Channel *channel)
    {
        _poller.RemoveEvent(channel);
    }

    // 当epoll事件通知完毕之后执行任务池中所有的任务
    void RunAllTask()
    {
        std::vector<Functor> tmp;
        {
            // 用对象的互斥锁来初始化一把锁，走到 } 自动释放
            std::unique_lock<std::mutex> lock(_mutex);

            // 交换_task和tmp的内容让tmp来执行_task中所有的任务
            _tasks.swap(tmp);
        }

        for (auto &fun : tmp)
        {
            fun();
        }

        return;
    }

    void AddTimer(uint64_t id, uint32_t delay, const Functor &cb)
    {
        return _time_wheel.AddTimer(id, delay, cb);
    }

    void RefreshTimer(uint64_t id)
    {
        return _time_wheel.RefreshTimer(id);
    }

    void CancelTimer(uint64_t id)
    {
        return _time_wheel.CancelTimer(id);
    }

    bool HasTimer(uint64_t id)
    {
        return _time_wheel.HasTimer(id);
    }

    // 启动：1.先进行事件监控 2.就绪事件的处理 3.执行任务
    void Start()
    {
        while (true)
        {
          //  DBG_LOG("eventloop开始监控：%p", this);
            // 1. 事件监控
            std::vector<Channel*> actives;
            _poller.Poll(&actives);
            // DBG_LOG("eventloop开始处理事件：%p", this);
        
            // 2. 事件处理
            for (auto& channel : actives)
            {
                channel->HandlerEvent();
            }

            // 3. 执行任务
            RunAllTask();
        }
    }

private:
    // 用于事件通知的fd
    int _eventfd;
    // 管理_eventfd事件的Channel对象，因为我们这里用的是指针来进行管理那么在EventLoop对象析构的时候要对保证不会内存泄漏，我们采用智能指针
    std::unique_ptr<Channel> _eventfd_channel;

    // 任务池(以队列的逻辑形式先进先出)
    std::vector<Functor> _tasks;
    // 保证拿任务时的线程安全的锁
    std::mutex _mutex;

    // 该EventLoop对象对应的线程ID
    std::thread::id _thread_id;

    // Poller对象,用于管理事件监控
    Poller _poller;

    // TimeWheel对象时间轮
    TimeWheel _time_wheel;
};


// EventLoop对应的线程的设计
// 一个EventLoop对象对应一个LoopThread对象
class LoopThread
{
private:
    // 实例化Eventloop对象，唤醒在条件变量下等待的线程，并且运行EventLoop的功能模块
    void ThreadEntry()
    {
        // 1.实例化EventLoop对象，我们这里使用一个临时变量而不是new一个对象：
        // 生命周期跟着LoopThread对象走
        EventLoop loop;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _loop = &loop;

            // 2.唤醒在条件变量下等待的线程
            _cond.notify_all();
        }
        std::cout << "ThreadEntry() :: eventloop" << &loop << std::endl;
        // 3.运行EventLoop的功能模块
        loop.Start();
    }

public:
    LoopThread()
    :_thread(std::thread(&LoopThread::ThreadEntry, this))
    ,_loop(nullptr)
    {}

    // 有线程安全问题要加锁
    EventLoop *GetLoop()
    {
        EventLoop *loop = nullptr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // _loop为空就阻塞在此
            // _cond.wait(lock, [&](){return loop != nullptr;}); //这里这个loop肯定是null呀...
            _cond.wait(lock, [&](){return _loop != nullptr;}); //这里应该判断的是这个成员

            loop =_loop;
        }

        return loop;
    }

private:
    // EventLoop对象对应的线程  
    std::thread _thread; 

    // 用于实现_loop获取同步关系，避免了线程创建了但是_loop对象没有被创建但是用户呀获取_loop的地址
    std::mutex _mutex;
    std::condition_variable _cond;

    // EventLoop对象的地址，这个对象要在线程内实例化
    EventLoop *_loop;
};

// 针对LoopThread所设计的线程池，便于使用者对线程进行管理和分配
// 我们设计的服务器是主从Reactor模型哦
class LoopThreadPool
{
public:
    LoopThreadPool(EventLoop *baseloop)
    :_baseloop(baseloop)
    ,_thread_count(0)
    ,_next_loop_index(0)
    {}

    // 设置从属的线程数量
    void SetThreadcount(int thread_count)
    {
        _thread_count = thread_count;
    }

    // 获取下一个线程对应的EventLoop对象
    EventLoop *GetNextLoop()
    {
        if (_thread_count == 0)
        {
            // 如果没有从属线程，返回主loop
            return _baseloop;  
        }
    
        EventLoop* loop = _loops[_next_loop_index];
        _next_loop_index = (_next_loop_index + 1) % _thread_count;
        return loop;
    }

    // 创建所有的从属线程
    void Create()
    {
        if(_thread_count > 0)
        {
            // 对两个管理数组进行扩容，不能一边插入一边扩容因为vector的扩容规则不是按照个数来的
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);

            // 对从属线程进行一个个的创建
            for(int i = 0; i<_thread_count; i++)
            {
                _threads[i] = new LoopThread();
                _loops[i] = _threads[i]->GetLoop();
            }
        }
    }
private:
    // 从属线程的个数
    int _thread_count;

    // 下一个EventLoop对象对应的在数组中的下标
    int _next_loop_index;

    // 主从Reactor模型中的主Reactor模型对应的EventLoop对象，该EventLoop对象运行在主线程之中
    EventLoop *_baseloop;

    // 保存所有的LoopThread对象(先描述再组织的体现)
    std::vector<LoopThread*> _threads;
    // 保存所有的LoopThread对象对应的EventLoop对象，在这里面的都是从属EventLoop
    std::vector<EventLoop*> _loops;
};

// 对链接的全方位管理，对通信链接的所有操作都在这里完成
// 一个Connection对象对应一个EventLoop对象对应一个执行线程保证线程安全问题
// 我们所有的Connection对象用shared_ptr进行管理
typedef enum
{
    DISCONNECTED,
    CONNECTING,
    CONNECTED,
    DISCONNECTING
} ConnStatu;

class Connection;
using PtrConnection = std::shared_ptr<Connection>;
using ConnectedCallback = std::function<void(const PtrConnection &)>;         // 连接建立完成之后的回调
using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>; // 消息来临的时候的回调 -- 处理相关数据
using ClosedCallback = std::function<void(const PtrConnection &)>;            // 挂断事件的回调
using AnyEventCallback = std::function<void(const PtrConnection &)>;          // 任意事件的回调 -- 如刷新活跃度
class Connection : public std::enable_shared_from_this<Connection>
{
private:
    // fd可读事件触发之后调用这个函数，接收内核Socket缓冲区的数据放到接收Buffer里面，然后调用_msg_callback来处理
    void HandleRead()
    {
        DBG_LOG("HandleRead called for fd: %d", _sockfd);
        char buffer[65536];
        int ret = _socket.NonBlockRecv(buffer, 65535);
        DBG_LOG("Received %d bytes", ret);
        if (ret < 0)
        {
            DBG_LOG("=== Recv error, shutting down ===");
            // 出错不可以直接关闭连接因为可能有数据没有处理完
            return ShutdownInLoop();
        }
        else if (ret == 0)
        {
            DBG_LOG("=== Recv returned 0, no data ===");
            // 这里表示没有读取到数据而不是关闭连接
            return;
        }

        DBG_LOG("=== Writing %d bytes to buffer ===", ret);
        _in_buffer.WriteAndPush(buffer, ret);
        if (_in_buffer.ReadAbleSize() > 0)
        {
            DBG_LOG("=== Calling message callback, readable=%lu ===", _in_buffer.ReadAbleSize());
            // 代表数据写入_in_buffer成功
            return _msg_callback(shared_from_this(), &_in_buffer);
        }
    }

    // 文件描述符触发可写事件后调用该函数，将发送缓冲区的数据发送
    void HandleWrite()
    {
        // 如果当前的连接处于将关闭的状态，有数据则发送，没有数据就释放
        if (_out_buffer.ReadAbleSize() == 0 && _statu == DISCONNECTING)
        {
            return ReleaseInLoop();
        }
        ssize_t ret = _socket.NonBlockSend(_out_buffer.Begin(), _out_buffer.ReadAbleSize());
        // 发送出错了就关闭连接
        if (ret < 0)
        {
            // 在关闭连接之前要先看一下接收缓冲区里面还有没有数据要处理
            if (_in_buffer.ReadAbleSize() > 0)
            {
                _msg_callback(shared_from_this(), &_in_buffer);
            }

            return ReleaseInLoop(); // 这是实际的关闭连接操作
        }

        // 数据从_out_buffer发送完成之后一定要讲_out_buffer的位置向后移，不然会一直发送数据
        _out_buffer.MoveReadPos(ret);
        // 数据发送完毕之后_out_buffer的内容为空对应的事件管理取消对写事件的监控
        if (_out_buffer.ReadAbleSize() > 0)
        {
            _channel.DisableWrite();
        }
    }

    // 文件描述符触发挂断事件
    void HandleClose()
    {
        // 先看一下还有没有事件要进行处理，有数据就先调用回调然后关闭连接，没有的话就直接关闭连接
        if (_in_buffer.ReadAbleSize())
        {
            _msg_callback(shared_from_this(), &_in_buffer);
        }

        return ReleaseInLoop(); // 这是实际的关闭连接操作
    }

    // 文件描述符触发错误事件
    void HandleError()
    {
        // 直接执行HandleClose()就行
        return HandleClose();
    }

    // 文件描述符触发了任意事件
    void HandleAnyEvent()
    {
        // 1.先检查是否启动了非活跃销毁的选项，启动了就刷新活跃度
        if (_enable_inactive_release == true)
        {
            // 传入_id因为我们用_conn_id来充当的_timer_id
            _loop->RefreshTimer(_id);
        }

        // 2.调用组件使用者设置的回调函数
        if (_any_callback)
        {
            _any_callback(shared_from_this());
        }
    }

    // 获取连接之后，进行设置连接的相关属性，调用回调函数，启动读监控
    void EstablishedInLoop()
    {
        static std::atomic<int> global_call_count{0};
    int call_num = ++global_call_count;
    
    std::cout << "ESTABLISHED CALL #" << call_num 
              << " - this: " << this 
              << " - Thread: " << std::this_thread::get_id() << std::endl;

        
        // DBG_LOG("=== EstablishedInLoop called, fd=%d ===", _sockfd);
        // 1.设置连接状态
        // 上层使用者调用次函数前连接的状态一 定是建立中
        std::cout << __FILE__ << __LINE__  << "_statu :" << _statu << "   CONNECTING" << CONNECTING << std::endl;
        assert(_statu == CONNECTING); //-------------------这里断言失败了 ，没看到你在哪里初始化statu了
        // 调用了该函数之后连接就处于建立完成的状态
        _statu = CONNECTED;

       // DBG_LOG("=== Enabling read event for fd=%d ===", _sockfd);
        // 2. 启动读事件的监控
        _channel.EnableRead();

        //DBG_LOG("=== Read event enabled, calling connected callback ===");
        // 3.调用连接建立完成的回调
        if (_conn_callback)
        {
            _conn_callback(shared_from_this());
        }

       // DBG_LOG("=== EstablishedInLoop completed ===");
        fflush(stdout);
    }

    // 实际的连接关闭接口
    void ReleaseInLoop()
    {
        // 1.设置连接的状态为关闭状态
        _statu = DISCONNECTED;

        // 2.移除对连接事件的监控
        _channel.Remove();

        // 3. 关闭文件描述符
        _socket.Close();

        // 4.如果在任务时间轮中有取消定时任务的任务要处理，则取消任务
        //   因为我们ReleaseInLoop是实际关闭连接的操作，对象被销毁了到时候时间轮任务执行的时候拿到的是非法的内存地址
        if (_loop->HasTimer(_id))
        {
            CancelInactiveReleaseInLoop();
        }

        // 要先调用自己的回调函数再调用服务器的关闭回调函数，
        // 因为先调用服务器的关闭回调函数会导致管理该连接的对象被销毁，后续的自己的关闭回调野指针访问了
        // 5.调用关闭的回调函数
        if (_clos_callback)
        {
            _clos_callback(shared_from_this());
        }

        // 6.调用服务器的关闭回调函数，将管理该连接的对象进行释放
        if (_server_close_callback)
        {
            _server_close_callback(shared_from_this());
        }
    }

    // 下面的这个接口不是对应的发送接口而是把数据写到_out_buffer中，启动可写事件的监控 --- 和上述的HandleWrite()接口配套的
    void SendInLoop(const char *data, int len)
    {
        // 1.先判断连接的状态
        if (_statu == DISCONNECTED)
        {
            return;
        }

        // 2.将数据写入_out_buffer中并且移动_out_buffer的可读位置
        _out_buffer.WriteAndPush(data, len);

        // 3.启动可写事件的监控
        if (_channel.WriteAble() == false)
        {
            _channel.EnableWrite();
        }
    }

    // 不是的实际的关闭连接操作，设置连接状态和判断还有没有数据要处理
    void ShutdownInLoop()
    {
        // 1.设置连接的状态
        _statu = DISCONNECTING;

        // 2.判断两个buffer里面还有没有数据要处理
        if (_in_buffer.ReadAbleSize() > 0)
        {
            _msg_callback(shared_from_this(), &_in_buffer);
        }

        if (_out_buffer.ReadAbleSize() > 0)
        {
            if (_channel.WriteAble())
            {
                _channel.EnableWrite();
            }
        }

        if (_out_buffer.ReadAbleSize() == 0)
        {
            ReleaseInLoop();
        }
    }

    // 启动定时销毁任务，并添加到任务池里面
    void EnableInactiveReleaseInLoop(int sec)
    {
        // 1.设置标志位
        _enable_inactive_release = true;

        // 2.判断任务池里面有没有定时销毁的任务，没有就添加，有就进行刷新
        if (_loop->HasTimer(_id))
        {
            _loop->RefreshTimer(_id);
        }
        else
        {
            // AddTimer(uint64_t id, uint32_t delay, const Functor &cb)
            // using Functor = std::function<void()>;
            _loop->AddTimer(_id, sec, std::bind(&Connection::ReleaseInLoop, this));
        }
    }

    // 取消定时销毁任务
    void CancelInactiveReleaseInLoop()
    {
        // 1.更改标志位
        _enable_inactive_release = false;

        // 2.检查再任务池里面有没有定时销毁任务有就进行取消
        if (_loop->HasTimer(_id))
        {
            _loop->CancelTimer(_id);
        }
    }

    // 协议的切换 -- 上下文的切换，回调函数的切换
    void UpgradeInLoop(const std::any &context, const ConnectedCallback &conn_callback, const MessageCallback &msg_callback,
                       const ClosedCallback &clos_callback, const AnyEventCallback &any_callback)
    {
        _context = context;
        _conn_callback = conn_callback;
        _msg_callback = msg_callback;
        _clos_callback = clos_callback;
        _any_callback = any_callback;
    }

public:
    // 构造函数
    Connection(EventLoop *loop, uint64_t id, int sockfd)
        : _loop(loop), _id(id), _sockfd(sockfd), _socket(_sockfd), _channel(_sockfd, loop), _enable_inactive_release(false), _statu(CONNECTING)
    {
        // 对_channel对象的回调函数的设置
        // using EventCallback = std::function<void()>;
        std::cout << "_statu : "<< _statu << std::endl;
        _channel.SetCloseCallback(std::bind(&Connection::HandleClose, this));
        _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
        _channel.SetEventsCallback(std::bind(&Connection::HandleAnyEvent, this));
        _channel.SetReadCallback(std::bind(&Connection::HandleRead, this));
        _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));

        // 启动channel对象的读事件监控不可以再构造中完成，因为我们走到这里还有一些的回调函数没有设置一旦触发了读事件会导致错误
    }

    // 获得文件描述符
    int GetFd()
    {
        return _sockfd;
    }

    // 获取Connection对象的ID
    uint64_t GetId()
    {
        return _id;
    }

    // 连接是都处于已经建立的状态
    bool IsConncted()
    {
        return (_statu == CONNECTED);
    }

    // 获取上下文的指针
    std::any *GetContext()
    {
        return &_context;
    }

    // 设置上下文
    void SetContext(std::any &context)
    {
        _context = context;
    }

    // 对private中一系列的*InLoop函数的接口设计
    // 设计思想将上述private中的所有的任务全部push到任务池中由一个线程执行，
    // Connection对象的成员变量中有一个EventLoop*可以使用

    // void IsRunInLoop(const Functor &cb)
    // using Functor = std::function<void()>;
    void Established()
    {
        std::cout << "Established()" << std::endl;
        _loop->IsRunInLoop(std::bind(&Connection::EstablishedInLoop, this));
    }

    void Send(const char *data, int len)
    {
        _loop->IsRunInLoop(std::bind(&Connection::SendInLoop, this, data, len));
    }

    void Shutdown()
    {
        _loop->IsRunInLoop(std::bind(&Connection::ShutdownInLoop, this));
    }

    void EnableInactiveRelease(int sec)
    {
        // std::function<void()> temp = std::bind(&Connection::EnableInactiveReleaseInLoop, sec, this);
        _loop->IsRunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec));
    }

    void CancelInactiveRelease()
    {
        _loop->IsRunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop, this));
    }

    void Upgrade(const std::any &context, const ConnectedCallback &conn_callback, const MessageCallback &msg_callback,
                 const ClosedCallback &clos_callback, const AnyEventCallback &any_callback)
    {
        // 在协议切换的时候，重置上下文以及回调函数的设置都是非线程安全的
        _loop->AssertInLoop();
        _loop->IsRunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn_callback, msg_callback, clos_callback, any_callback));
    }

    // 对几个回调函数的设置
    void SetConnectedCallback(const ConnectedCallback &conn_callback)
    {
        _conn_callback = conn_callback;
    }

    void SetMessageCallback(const MessageCallback &msg_callback)
    {
        _msg_callback = msg_callback;
    }

    void SetClosedCallback(const ClosedCallback &clos_callback)
    {
        _clos_callback = clos_callback;
    }

    void SetAnyEventCallback(const AnyEventCallback &any_callback)
    {
        _any_callback = any_callback;
    }

    void SetServerClosedCallback(const ClosedCallback &server_close_callback)
    {
        _server_close_callback = server_close_callback;
    }

private:
    // 每个connection对象的唯一标识符
    uint64_t _id;
    // uint64_t _time_id;(定时器ID，在这里用_id来代替)

    // Connection对象管理的文件描述符
    int _sockfd;
    // 对文件描述符进行各种操作的Socket对象
    Socket _socket;
    // 对一个链接事件的管理
    Channel _channel;

    // 接收缓冲区 -- 将数据从内核Socket缓冲区拷贝过来，等到了读事件就绪就触发回调
    Buffer _in_buffer;
    // 发送缓冲区 -- 将发送给对端的数据暂时存在这儿离，等到了写事件就绪就触发回调
    Buffer _out_buffer;

    // 用于保存请求的上下文 -- 因为server对数据的处理有可能会因为对端发送的不是一个完整的报文而只处理一部分
    //                       这个时候就需要保存处理到了哪里以便下一次的处理
    std::any _context;

    // 当前链接的状态 -- DISCONNECTED(连接关闭)，DISCONNECTING(连接处于待关闭的状态--用户想要关闭连接但是有数据没有处理完成)
    //                  CONNECTING(连接建立中--回调没有设置好)，CONNECTED(连接建立完成)
    ConnStatu _statu;

    // 四个由组件的使用者设置的回调函数
    ConnectedCallback _conn_callback;
    MessageCallback _msg_callback;
    ClosedCallback _clos_callback;
    AnyEventCallback _any_callback;
    // 组件内的连接关闭回调，组件内设置，因为Server组件会把所有的连接管理起来，一旦连接要关闭，就该从管理的地方删除改连接
    ClosedCallback _server_close_callback;

    // 判断该连接是否启动了非活跃关闭的功能，默认为false
    bool _enable_inactive_release;

    // 一个Connection对象关联的EventLoop对象对应关联的线程
    EventLoop *_loop;
};

using AcceptCallback = std::function<void(int)>;
// 对监听套接字的管理(获取新连接之后该怎么处理)
class Accptor
{
private:
    // 对于监听套接字只需要监控读事件就行
    void HandlerRead()
    {
        // 1.通过监听套接字的Socket对象获取新连接
     //   DBG_LOG("获取新连接.........");
        int newfd = _socket.Accept();
        // 2.执行上层的回调函数
        if(_accept_callback)
        {
            _accept_callback(newfd);
        }
    }

    int CreateServer(int port)
    {
        bool ret = _socket.CreatServerLink(port);
        assert(ret != false);

        return _socket.Getfd();
    }

public:
    Accptor(EventLoop *loop, int port)
    :_socket(CreateServer(port))
    ,_loop(loop)
    ,_channel(_socket.Getfd(), _loop)
    {
        DBG_LOG("创建监听套接字：%d", (_socket.Getfd()));
        // 为Channel对象设置回调
        _channel.SetReadCallback(std::bind(&Accptor::HandlerRead, this));
        // _channel.EnableRead();
    }

    void SetAcceptCallback(AcceptCallback accept_callback)
    {
        _accept_callback = accept_callback;
    }

    void Listen()
    {
        // 启动_channel的可读
        _channel.EnableRead();
    }

private:
    // Socket对象用于对监听套接字的创建
    Socket _socket;

    // 监听套接字的事件管理对象
    EventLoop *_loop;

    // 监听套接字的事件监控对象
    Channel _channel;

    // 获取到新连接之后的回调函数，给Server模块使用的(创建Connection对象)
    AcceptCallback _accept_callback;
};


// 服务器类，实例化一个服务器对象就可以进行工作
class TcpServer
{
private:
    void RunAfterInLoop(const Functor& task, int delay)
    {
        // 增加对应的ID值
        _conn_id++;

        // 将任务推入到任务池中
        _baseloop.AddTimer(_conn_id, delay, task);
    }

    // 为指定的文件描述符创建一个Connection对象
    void NewConnection(int fd)
    {
        // 先让_conn_id自增
        _conn_id++;
        //DBG_LOG("有新连接到来。。。。。。。");
        // Coonnection的构造：Connection(EventLoop *loop, uint64_t id, int sockfd)
        // _pool.GetNextLoop()返回的是一个EventLoop对象的指针
        std::shared_ptr<Connection> Newconn = std::make_shared<Connection>(_pool.GetNextLoop(), _conn_id, fd);
        std::cout << "---------------------NewConnection---------------------" << std::endl;
        // 四个回调函数的设置，将TcpServer中的四个回调函数变量设置进入Newconn对象
        Newconn->SetMessageCallback(_message_callback);
        Newconn->SetClosedCallback(_closed_callback);
        Newconn->SetConnectedCallback(_connected_callback);
        Newconn->SetAnyEventCallback(_anyevent_callback);

        // 设置服务器关闭的回调函数
        Newconn->SetServerClosedCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));

        // 如果启动了超时连接销毁就要设置超时销毁时间
        if(_enable_inactive_release == true)
        {
            Newconn->EnableInactiveRelease(_timeout);
        }

        // Newconn对象就绪初始化
        Newconn->Established();

        // 将新增的Newconn对象添加到管理信息中
        _conns.insert(std::make_pair(_conn_id, Newconn));
    }

    // 移除Connection对象从哈希表中移除
    void RemoveConnectionInLoop(const std::shared_ptr<Connection> &conn)
    {
        auto it = _conns.find(conn->GetId());
        _conns.erase(it);
    }

    // 移除Connection对象
    void RemoveConnection(const std::shared_ptr<Connection> &conn)
    {
        _baseloop.IsRunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }
   
public:
    TcpServer(int port)
    :_port(port)
    ,_conn_id(0)
    ,_enable_inactive_release(false)
    ,_pool(&_baseloop)
    ,_acceptor(&_baseloop, port)
    {
        _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1));
        // 将监听套接字挂到_baseloop上开始启动监听
        _acceptor.Listen();
    }

    // 四个回调函数的设置
    // 连接建立成功的回调函数
    void SetConnectedCallback(const ConnectedCallback &connected_callback)
    {
        _connected_callback = connected_callback;
    }

    // 消息来临的回调函数
    void SetMessageCallback(const MessageCallback &message_callback)
    {
        _message_callback = message_callback;
    }

    // 关闭事件到来的回调函数
    void SetClosedCallback(const ClosedCallback &closed_callback)
    {
        _closed_callback = closed_callback;
    }

    // 任意事件的回调函数
    void SetAnyEventCallback(const AnyEventCallback &anyevent_callback)
    {
        _anyevent_callback = anyevent_callback;
    }

    // 设置从属的线程个数
    void SetThreadCount(int tcount)
    {
        _pool.SetThreadcount(tcount);
    }

    // 设置超时释放连接的功能
    void EnableInactiveRelease(int timeout)
    {
        // 设置标志位
        _enable_inactive_release = true;
        // 设置超时释放时间
        _timeout = timeout;
    }

    // 执行的下一个任务，以及执行下一个任务的延时时间
    void RunAfter(const Functor& task, int delay)
    {
        _baseloop.IsRunInLoop(std::bind(&TcpServer::RunAfterInLoop, this, task, delay));
    }

    // 服务器的启动
    void Start()
    {
        // 创建线程池中的从属线程
        DBG_LOG("创建reactor线程池......");
        _pool.Create(); //这个函数内部在哪里卡住了，所以没有执行下去，导致baseloop没有被启动...

        DBG_LOG("创建reactor线程池完毕，准备启动baseloop......");
        // 启动主线程
        _baseloop.Start();
    }


private:
    // 自动增长的连接ID
    uint64_t _conn_id;

    // 主线程的EventLoop对象负责监听套接字的事件管理
    EventLoop _baseloop; //顺序错了，这个要放到acceptor前边，因为acceptor的构造依赖这个对象

    // 监听套接字的管理对象
    Accptor _acceptor;


    // _baseloop从属的线程池
    LoopThreadPool _pool;

    // 管理所有连接对应Connection对象
    std::unordered_map<uint64_t, std::shared_ptr<Connection>> _conns;

    // 是否启动对非活跃连接销毁的功能
    bool _enable_inactive_release;

    // 非活跃连接多长时间后销毁
    int _timeout;

    // 服务器的监听端口
    int _port;

    // 四个事件回调函数的设置
    ConnectedCallback _connected_callback; // 连接建立成功之后的回调
    MessageCallback _message_callback; // 消息来临时的回调
    ClosedCallback _closed_callback; // 关闭事件来临时的回调
    AnyEventCallback _anyevent_callback; //任意事件的回调
};

void Channel::Update()
{
    _eventloop->UpdateEvent(this);
}

void Channel::Remove()
{
    _eventloop->RemoveEvent(this);
}

void TimeWheel::Remove(uint64_t id)
{
    auto pos = _mmap.find(id);
    if (pos == _mmap.end())
        {
            std::cerr << "找不到对应的任务对象！" << std::endl;
            return;
        }

        // 找到了
        _mmap.erase(pos);
    }

    int TimeWheel::CreateTimerfd()
    {
        int tmp = timerfd_create(CLOCK_MONOTONIC, 0);
        if (tmp < 0)
        {
            ERR_LOG("CREATE TIMERFD FAILED!");
        }

        // 创建成功，对timerfd进行set，将old_value部分设置为空
        struct itimerspec new_value;
        new_value.it_interval.tv_sec = 1;
        new_value.it_interval.tv_nsec = 0;
        new_value.it_value.tv_sec = 1;
        new_value.it_value.tv_nsec = 0;

        int ret = timerfd_settime(tmp, 0, &new_value, nullptr);
        if (ret < 0)
        {
            ERR_LOG("SET TIMERFD FAILED!");
        }

        return tmp;
    }

    void TimeWheel::ReadTimerfd()
    {
        uint64_t time;
        int ret = read(_timerfd, &time, 8);
        if (ret < 0)
        {
            return;
        }
    }

    // 秒针每秒向后走一次
    void TimeWheel::Run()
    {
        _tick = (_tick + 1) % _capactiy;
        _wheel[_tick].clear(); // 释放数组中的对象
    }

    void TimeWheel::OnTime()
    {
        ReadTimerfd();
        Run();
    }

    // 向哈希表中增加一个新的weak_ptr对象 + 轮子里面增加shared_ptr管理的Task对象
    void TimeWheel::AddTimerInLoop(uint64_t id, uint32_t delay, const TaskFun &cb)
    {
        // step1. 构建shared_ptr对象，并设置相关函数
        std::shared_ptr<Task> task = std::make_shared<Task>(id, delay, cb);
        task->SetReleaseFun(std::bind(&TimeWheel::Remove, this, id)); // 注意不使用bind会导致参数不匹配问题

        // 添加到管理部分
        _mmap[id] = std::weak_ptr<Task>(task);

        int pos = (_tick + delay) % _capactiy;
        // 添加到执行部分
        _wheel[pos].emplace_back(task);
    }

    // 轮子里面增加shared_ptr管理的Task对象
    void TimeWheel::RefreshTimerInLoop(uint64_t id)
    {
        auto it = _mmap.find(id);
        if (it == _mmap.end())
        {
            std::cerr << "位置不存在!" << std::endl;
            return;
        }

        // 找到了
        // 添加到执行部分
        std::shared_ptr<Task> task = it->second.lock();
        int pos = (_tick + task->Gettimeout()) % _capactiy;
        _wheel[pos].push_back(task);
    }

    // 取消定时任务方法：不能直接在数组中释放掉管理的对象，这并不会取消而是提前执行
    void TimeWheel::CancelTimerInLoop(uint64_t id)
    {
        auto it = _mmap.find(id);
        if (it == _mmap.end())
        {
            std::cerr << "位置不存在!" << std::endl;
            return;
        }

        // 找到了
        // 添加到执行部分
        std::shared_ptr<Task> task = it->second.lock();
        task->SetCancel();
    }

    bool TimeWheel::HasTimerInLoop(uint64_t id)
    {
        auto it = _mmap.find(id);
        if (it == _mmap.end())
        {
            return false;
        }

        return true;
    }

    inline TimeWheel::TimeWheel(EventLoop *loop)
        : _tick(0), _capactiy(60), _wheel(60), _loop(loop), _timerfd(CreateTimerfd()), _timer_channel(std::make_unique<Channel>(_timerfd, loop))
    {
        // 设置_timerfd的可读回调
        _timer_channel->SetReadCallback(std::bind(&TimeWheel::OnTime, this));
        // 启动可读
        _timer_channel->EnableRead();
    }

    // 对于定时任务的操作：有可能会出现线程安全问题，
    // 比如一个线程对_task中的一个元素在进行刷新，同一时刻另外一个线程对同一元素进行删除
    // 我们要确保刷新等操作都要在同一个线程中，压入Eventloop的任务池
    void TimeWheel::AddTimer(uint64_t id, uint32_t delay, const TaskFun &cb)
    {
        _loop->IsRunInLoop(std::bind(&TimeWheel::AddTimerInLoop, this, id, delay, cb));
    }

    void TimeWheel::RefreshTimer(uint64_t id)
    {
        _loop->IsRunInLoop(std::bind(&TimeWheel::RefreshTimerInLoop, this, id));
    }

    void TimeWheel::CancelTimer(uint64_t id)
    {
        _loop->IsRunInLoop(std::bind(&TimeWheel::CancelTimerInLoop, this, id));
    }

    bool TimeWheel::HasTimer(uint64_t id)
    {
        // return _loop->IsRunInLoop(std::bind(&TimeWheel::HasTimerInLoop, this, id));
        auto it = _mmap.find(id);
        if (it == _mmap.end())
        {
            return false;
        }
        return true;
    }



class NetWork
{
    public:
        NetWork()
        {
            DBG_LOG("SIGPIPE INIT");
            signal(SIGPIPE, SIG_IGN);
        }
};
// 设置一下构造函数的信号
static NetWork nw;